package codeGen.core;

import codeGen.core.model.FieldModel;
import codeGen.core.model.TableModel;
import org.apache.commons.lang3.StringUtils;

import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;


/**
 */
public class MysqlTableManager implements TableManager {

    private String tableSchema = "biz";
//    private String tableSchema = "biz";

    public void setTableSchema(String tableSchema) {
        this.tableSchema = tableSchema;
    }

    @Override
    public TableModel getTableFieldMap(String table) {
        return getTableFieldMap(table, "");
    }

    @Override
    public TableModel getTableFieldMap(String tableName, String alias) {
        TableModel tm = new TableModel();
        Connection conn = null;
        try {
            conn = ConnectionManager.getConnection();
            Statement stmt = conn.createStatement();
//            tm = queryDesc(stmt, tableName, alias);
            tm = queryInformationSchema(stmt, tableName, alias);
        } catch (SQLException ex) {
            ex.printStackTrace();
        } finally {
            try {
                if (null != conn) conn.close();
            } catch (SQLException e) {
                e.printStackTrace();
            }
        }
        return tm;
    }

    @Override
    public TableModel getTableFieldMap(String table, String alias, String tableSchema) {
        this.tableSchema = tableSchema;
        return getTableFieldMap(table, alias);
    }

    /**
     * 查询本数据库 用sql desc查询
     *
     * @param stmt
     * @param tableName
     * @param alias
     * @throws Exception
     */
    private TableModel queryDesc(Statement stmt, String tableName, String alias) throws SQLException {
        TableModel tm = new TableModel();
        ResultSet res = stmt.executeQuery("desc " + tableName);
        List<FieldModel> fields = new ArrayList<FieldModel>(0);
        List<FieldModel> primtives = new ArrayList<FieldModel>(0);
        while (res.next()) {
            //保存字段信息
            FieldModel fm = new FieldModel(res.getString("Field"),
                    BeanUtil.toMethodName(res.getString("Field")),
                    BeanUtil.toClassName(res.getString("Field")),
                    res.getString("Type"),
                    "PRI".equals(res.getString("Key")),
                    "auto_increment".equals(res.getString("Extra")),
                    "MUL".equals(res.getString("Key")),
                    res.getObject("Default"),
                    "YES".equals(res.getString("Null")));
            //主键
            if ("PRI".equals(res.getString("Key"))) {
                primtives.add(fm);
            }
            //自增字段
            if ("auto_increment".equals(res.getString("Extra"))) {
                tm.setHasFieldAutoIncrease(true);
                tm.setFieldAutoIncrease(res.getString("Field"));
                tm.setPrimeAutoIncreaseType(BeanUtil.toJavaType(res.getString("Type")));
            }
            fields.add(fm);
        }
        //表名称
        tm.setName(tableName);
        //映射实体类名称
        if ("".equals(alias)) {
            tm.setToClassName(BeanUtil.toClassName(tableName));
        } else {
            tm.setToClassName(alias);
        }
        //银蛇实体实例名称
        tm.setToEntityName(BeanUtil.toClassInstanceName(tableName));
        //字段集合
        tm.setFields(fields);
        //主键集合
        tm.setPrimtives(primtives);
        return tm;
    }


    /**
     * 查询系统数据库 information_schema
     * SELECT * from `COLUMNS` WHERE TABLE_NAME=?
     */
    private TableModel queryInformationSchema(Statement stmt, String tableName, String alias) throws SQLException {
        TableModel tm = new TableModel();
        String sqlSchema = "";
        if (StringUtils.isNotBlank(tableName)) {
            sqlSchema = " and TABLE_SCHEMA=\"" + tableSchema + "\"";
        }
        String sql = "SELECT * from `COLUMNS` WHERE TABLE_NAME=\"" + tableName + "\" " + sqlSchema + " ORDER BY ORDINAL_POSITION";
        ResultSet res = stmt.executeQuery(sql);
        // COLUMN_NAME   字段名
        // COLUMN_DEFAULT 默认值
        // IS_NULLABLE   可否为空
        // DATA_TYPE     字段类型
        // CHARACTER_MAXIMUM_LENGTH  字段长度
        // COLUMN_KEY     是否主键 "PRI"
        // COLUMN_COMMENT  注释
        List<FieldModel> fields = new ArrayList<>(0);
        List<FieldModel> primtives = new ArrayList<>(0);
        while (res.next()) {
            //保存字段信息
            String columnName = res.getString("COLUMN_NAME");
            String columnKey = res.getString("COLUMN_KEY");
            String columnType = res.getString("DATA_TYPE");
            String columnIncrement = res.getString("Extra");

            FieldModel fm = new FieldModel(columnName,
                    BeanUtil.toClassName(columnName),
                    BeanUtil.toMethodNameCamelCase(columnName.toLowerCase()),
                    columnType,
                    "PRI".equals(columnKey),
                    "auto_increment".equals(columnIncrement),
                    "MUL".equals(columnKey),
                    res.getObject("COLUMN_DEFAULT"),
                    "YES".equals(res.getString("IS_NULLABLE")));
            //主键
            if ("PRI".equals(columnKey)) {
                primtives.add(fm);
            }
            //自增字段
            if ("auto_increment".equals(columnIncrement)) {
                tm.setHasFieldAutoIncrease(true);
                tm.setFieldAutoIncrease(columnName);
                tm.setPrimeAutoIncreaseType(BeanUtil.toJavaType(columnType));
            }
            fm.setComment(res.getString("COLUMN_COMMENT"));
            fields.add(fm);
        }
        //表名称
        tm.setName(tableName);
        //映射实体类名称
        if ("".equals(alias)) {
            tm.setToClassName(BeanUtil.toClassName(tableName));
        } else {
            tm.setToClassName(alias);
        }
        //映射实体实例名称
        tm.setToEntityName(BeanUtil.toClassInstanceName(tableName));
        //字段集合
        tm.setFields(fields);
        //主键集合
        tm.setPrimtives(primtives);
        return tm;
    }
}
